
package urbanparks;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;

/**
 * This class is used to hold information for a created
 * Job.  Once created the Job object can be accessed to
 * add and remove volunteers from a specific Job Grade.
 * There are 3 job grade classes associated with each
 * level of difficulty.  
 * 
 * @author Ben Hadorn
 * @version Winter 2012
 *
 */
public class Job {
  
  /**
   * Static int used to represent the light job grade.
   */
  public final static int LIGHT_GRADE = 0;
  
  /**
   * Static int used to represent the medium job grade.
   */
  public final static int MEDIUM_GRADE = 1;
  
  /**
   * Static int used to represent the heavy job grade.
   */
  public final static int HEAVY_GRADE = 2;
  
  /**
   * Labels for the different job difficulties.
   */
  private final String[] my_difficulties = {"LIGHT", "MEDIUM", "HIGH"};
  
  /**
   * The list containing all of the job grades.
   */
  private final List<JobGrade> my_job_grades = new ArrayList<JobGrade>();
  
  /**
   * A reference to the job duration object.
   */
  private final JobDuration my_job_duration;
  
  /**
   * The description of this job object.
   */
  private final String my_job_description;
  
  /**
   * The park name of the park that this job is located at.
   */
  private final String my_job_location;
  
  /**
   * The email of the manager that manages the park that this job is located at.
   */
  private final String my_manager;
  
  /**
   * The date that the job was received or read in.
   */
  private final Calendar my_received_date;
  
  /**
   * The email of the user that added the job.
   */
  private final String my_received_by;
  
  /**
   * A constructor that is used when loading a job in from a file.  It takes all of the information required
   * but the constructor to create a new job with one additional field. It takes a list of lists of strings, which holds 
   * three lists representing the job grade volunteers.  These lists are held in order of lowest to highest job grade 
   * difficulties.
   * @param the_received_by the Urban Parks user that received the job request.
   * @param the_job_description the description of the job.
   * @param the_job_location the park name.
   * @param the_manager_email the park manager's email address.
   * @param the_descriptions a list of strings that holds the descriptions for the Job Grades in lowest to highest difficulty.
   * @param the_max_volunteers a list of the maximum volunteers that are needed for the Job Grades list same as descriptions. 
   * @param the_job_duration an integer array holding 4 values. Job start year, month, day, and # of days the job lasts.
   * @param the_user_list the list of lists of strings holding the volunteers already signed up for specific job grades.
   */
  public Job(final String the_received_by,
             final String the_job_description,
             final String the_job_location,
             final String the_manager_email,
             final List<String> the_descriptions, 
             final List<Integer> the_max_volunteers,
             final int[] the_job_duration,
             final List<List<String>> the_user_list) {
    my_received_date = Calendar.getInstance();
    my_received_by = the_received_by;
    my_job_description = the_job_description;
    my_job_location = the_job_location;
    my_manager = the_manager_email;
    for (int i = 0; i < the_descriptions.size(); i++){
      my_job_grades.add(new JobGrade(my_difficulties[i], 
                                     the_descriptions.get(i), 
                                     the_max_volunteers.get(i)));
      for (String s : the_user_list.get(i)) {
        my_job_grades.get(i).addUserToGrade(s);
      }
    }
    my_job_duration = new JobDuration(the_job_duration[0], 
                                      the_job_duration[1], 
                                      the_job_duration[2], 
                                      the_job_duration[3]);
  }
  /**
   * A constructor that creates a new job and also records the information of the Urban Parks user that entered the job.
   * @param the_received_by the Urban Parks user that received the job request.
   * @param the_job_description the description of the job.
   * @param the_job_location the park name.
   * @param the_manager_email the park manager's email address.
   * @param the_descriptions a list of strings that holds the descriptions for the Job Grades in lowest to highest difficulty.
   * @param the_max_volunteers a list of the maximum volunteers that are needed for the Job Grades list same as descriptions. 
   * @param the_job_duration an integer array holding 4 values. Job start year, month, day, and # of days the job lasts.
   */
  public Job(final String the_received_by,
             final String the_job_description,
             final String the_job_location,
             final String the_manager_email,
             final List<String> the_descriptions, 
             final List<Integer> the_max_volunteers,
             final int[] the_job_duration) {
    my_received_date = Calendar.getInstance();
    my_received_by = the_received_by;
    my_job_description = the_job_description;
    my_job_location = the_job_location;
    my_manager = the_manager_email;
    for (int i = 0; i < the_descriptions.size(); i++){
      my_job_grades.add(new JobGrade(my_difficulties[i], 
                                     the_descriptions.get(i), 
                                     the_max_volunteers.get(i)));
    }
    my_job_duration = new JobDuration(the_job_duration[0], 
                                      the_job_duration[1], 
                                      the_job_duration[2], 
                                      the_job_duration[3]);
    }

  /**
   * this method combines all of the sign up lists of all the job grades. This is used internally by addUser 
   * method to ensure no User signs up for the same job twice. This is also used as a query by outside classes.
   * @return A List that contains a list for each job grade that has a list of volunteers that are signed up at each grade.
   */
  public List<List<String>> getVolunteerList() {
    List<List<String>> tmp = new ArrayList<List<String>>();
    for( int i = 0; i < my_job_grades.size(); i++) {
      tmp.add(my_job_grades.get(i).getUserList());
    }
    return tmp;
  }
  
  /**
   * first check to ensure that user isn't signed up for a different Job Grade already associated with 
   * the same job. Additionally check to ensure the user isn't black balled preventing them from volunteering.
   * If he/she isn't, then find the appropriate Job Grade and add the user to it if there is room.
   * @param the_user the Volunteer.
   * @param the_grade the difficulty the User is signing up for.
   * @return a boolean true if added, false otherwise.
   */
  public boolean addVolunteer(final User the_user, final JobGrade the_grade, final JobSet the_jobset) {
    
    Volunteer temp = null;
    boolean added = false;
    boolean already_signed = false;
    
    try {
      
      temp = (Volunteer) the_user;
      
    } catch (final ClassCastException e) {
      //Do nothing
    }
    
    
  
    
    
    
    if(temp != null) {
      List<List<String>> tmp_list = getVolunteerList();
      for (List<String> user_list : tmp_list) {
        if (user_list.contains(the_user.getEmailAddress())) {
          already_signed = true;
        }
      }
      if (already_signed == false && !temp.isBlackballed() &&
          !the_jobset.isConflict(the_user, my_job_duration.getStartTime())){
        for( int i = 0; i < my_job_grades.size(); i++) {
          if (the_grade.toString().equalsIgnoreCase(my_job_grades.get(i).toString())) {
            added = my_job_grades.get(i).addUserToGrade(the_user.getEmailAddress());
          }
        }
      }
    }
    return added;
  }
  /**
   * Allows higher level classes to access the specific grade within a job.
   * @param the_grade is a string that will be compared to the toString method
   * of the Job Grade to identify the correct object.
   * @return JobGrade 
   */
  public JobGrade getGrade(final int the_grade) {
    
    return my_job_grades.get(the_grade);
  }
  /**
   * gets the JobDuration for this job
   * @return JobDuration object.
   */
  public JobDuration getJobDuration() {
    return my_job_duration;
  }
  /**
   * gets the description of this job
   * @return String.
   */
  public String getJobDescription() {
    return my_job_description;
  }
  /**
   * gets the name of the park the job is assigned to.
   * @return String.
   */
  public String getPark() {
    return my_job_location;
  }
  /**
   * gets the name of the Urban Parks user that received the job request.
   * @return String.
   */
  public String getReceivedBy() {
    return my_received_by;
  }
  /**
   * gets the date the job was received.
   * @return String.
   */
  public String getDateReceived() {
    DateFormat tmp = new SimpleDateFormat("MM-dd-yyyy");
    return tmp.format(my_received_date.getTime());
  }
  /**
   * Tests if the job start date is greater or equal to the current date.
   * 
   * @return True if the job's start date is greater than or equal to the current date.
   */
  public boolean isPendingJob() {
    return !my_job_duration.isPastJob();
  }
  /**
   * This method checks to see if a volunteer is already signed up for this job.
   * 
   * @param user_email_address The email address of the user.
   * @return boolean true if the user is signed and false otherwise.
   */
  public boolean containsVolunteer(String user_email_address) {
    boolean result = false;
    List<List<String>> tmp_list = getVolunteerList();
    for (List<String> list : tmp_list) {
      for (String u : list) {
        if (u.equalsIgnoreCase(user_email_address)) {
          result = true;
        }
      }
    }
    return result;
  }
  /**
   * gets the park managers name associated with this job
   * @return String.
   */
  public String getParkManager() {
    return my_manager;
  }
  
  /**
   * Returns a list of all of the volunteers signed up for this job without the
   * grade that each user signed up for.
   * 
   * @return A list of all the volunteers currently signed up for this job.
   */
  public List<String> getVolunteerListNoGrade() {
    final List<String> result = new LinkedList<String>();
    for (List<String> list : getVolunteerList()) {
      for (String s : list) {
        result.add(s);
      }
    }
    return result;
  }
  /**
   * Returns the formatted string that represents a job in the persistent data file.
   * 
   * @return A formatted string that represents a job in the persistent data file.
   */
  public String getFileString() {
    final StringBuilder result = new StringBuilder();
    final char c = ',';
    result.append(my_received_by);
    result.append(c);
    result.append(my_job_description);
    result.append(c);
    result.append(my_job_location);
    result.append(c);
    result.append(my_manager);
    result.append(c);
    result.append(my_job_grades.get(0).getDescription());
    result.append(c);
    result.append(my_job_grades.get(1).getDescription());
    result.append(c);
    result.append(my_job_grades.get(2).getDescription());
    result.append(c);
    result.append(my_job_grades.get(0).getMaxNeeded());
    result.append(c);
    result.append(my_job_grades.get(1).getMaxNeeded());
    result.append(c);
    result.append(my_job_grades.get(2).getMaxNeeded());
    result.append(c);
    result.append(my_job_duration.getYear());
    result.append(c);
    result.append(my_job_duration.getMonth());
    result.append(c);
    result.append(my_job_duration.getDay());
    result.append(c);
    result.append(my_job_duration.getJobLength());
    result.append(c);
    for (String s : getVolunteerList().get(0)) {
      result.append("low");
      result.append(c);
      result.append(s);
      result.append(c);
    }
    for (String s : getVolunteerList().get(1)) {
      result.append("medium");
      result.append(c);
      result.append(s);
      result.append(c);
    }
    for (String s : getVolunteerList().get(2)) {
      result.append("high");
      result.append(c);
      result.append(s);
      result.append(c);
    }
    return result.toString();
  }
  
  /**
   * overrides the toString and returns the job location.
   */
  @Override
  public String toString() {
    return my_job_location;
  }
  
  /**
   * Returns a formatted string that contains the park name and the job start date.
   * 
   * @return A formatted string that contains the park name and job start date.
   */
  public String toParkDateString() {
    final StringBuilder result = new StringBuilder();
    result.append(my_job_location);
    result.append(", ");
    result.append(my_job_duration.toString());
    return result.toString();
  }
  
  /**
   * Attempts to remove the volunteer from the signup lists.
   * 
   * @return True if the user was removed. False if the user was not signed up.
   */
  public boolean removeVolunteer(final String the_user_email) {
     boolean result = false;
    final JobGrade light = my_job_grades.get(LIGHT_GRADE);
    final JobGrade medium = my_job_grades.get(MEDIUM_GRADE);
    final JobGrade heavy = my_job_grades.get(HEAVY_GRADE);
    result = light.removeUserFromGrade(the_user_email);
    result = result || medium.removeUserFromGrade(the_user_email);
    result = result || heavy.removeUserFromGrade(the_user_email);
   
    return result;
  }

}
